package net.zdsoft.wpchat.support.action.advanced;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.lang.StringUtils;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;

import net.zdsoft.keel.action.ActionContext;
import net.zdsoft.keel.util.ArrayUtils;
import net.zdsoft.keel.util.LogbackUtils;
import net.zdsoft.keel.util.MathUtils;
import net.zdsoft.keel.util.ServletUtils;
import net.zdsoft.keel.util.Validators;
import net.zdsoft.wpchat.android.client.BasicAction;
import net.zdsoft.wpchat.support.dto.FileDto;

/**
 * 日志文件列表和日志文件修改模块Action
 * 
 * @author xuan
 * @version $Revision: 1.0 $, $Date: 2014-9-21 下午3:06:05 $
 */
public class LogAction extends BasicAction {
    private static final long serialVersionUID = 5634773806713158522L;

    private String logName;// 日志的文件名
    private String level;
    private String loggerName; // 日志的名称
    private String loggerNameKeyword; // 日志名称的关键字
    private Map<String, String> logger2LevelMap; // key为日志名称,value为日志级别的Map
    private List<File> logs;
    private final List<FileDto> logDtos = new ArrayList<FileDto>();

    /**
     * 获取日志列表
     * 
     * @return
     */
    public String logList() {
        logs = LogbackUtils.getAllLogFiles();
        Comparator<File> ctc = new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                long o1Long = o1.lastModified();
                long o2Long = o2.lastModified();
                long result = o1Long - o2Long;
                if (result > 0) {
                    return -1;
                }
                else if (result == 0) {
                    return 0;
                }
                else {
                    return 1;
                }
            }
        };
        Collections.sort(logs, ctc);

        double _length = 0;
        String unit = null;

        for (File _log : logs) {
            FileDto dto = new FileDto();
            long length = _log.length();
            if (length < 1024) {
                _length = _log.length();
                unit = "B";
            }

            else if (length >= 1024 && length < (1024 * 1024)) {
                _length = MathUtils.div(length, 1024, 2);
                unit = "KB";
            }

            else if (length >= (1024 * 1024) && length < (1024 * 1024 * 1024)) {
                _length = MathUtils.div(length, 1024 * 1024, 2);
                unit = "MB";
            }

            else if (length >= (1024 * 1024 * 1024)) {
                _length = MathUtils.div(length, 1024 * 1024 * 1024, 2);
                unit = "GB";
            }
            dto.setUnit(unit);
            dto.setLength(_length);
            dto.setName(_log.getName());
            dto.setLastModified(_log.lastModified());
            logDtos.add(dto);
        }
        return SUCCESS;
    }

    /**
     * 删除日志
     * 
     * @return
     */
    public String removeLog() {
        if (!Validators.isEmpty(logName) && !logName.contains("../")) {
            LogbackUtils.removeLogFile(logName);
        }
        return SUCCESS;
    }

    /**
     * 下载日志
     * 
     * @return
     */
    public String downloadLog() {
        if (!Validators.isEmpty(logName) && LogbackUtils.getLogFile(logName) != null && !logName.contains("../")) {
            try {
                ServletUtils.download(LogbackUtils.getLogFile(logName), ActionContext.getRequest(),
                        ActionContext.getResponse(), logName);
            }
            catch (Exception e) {
                logger.error("下载日志失败，原因：" + e.getMessage(), e);
            }
        }
        return SUCCESS;
    }

    /**
     * 修改日志级别
     * 
     * @return
     */
    public String modifyLoggerLevel() {
        initLogger2LevelMap();

        if (Validators.isEmpty(loggerName) || !logger2LevelMap.containsKey(loggerName)) {
            addActionError("请选择您要修改的日志");
            return INPUT;
        }

        if (Validators.isEmpty(level) || !ArrayUtils.contains(getAllLevels(), level)) {
            addActionError("请选择日志的级别");
            return INPUT;
        }

        LogbackUtils.setLoggerLevel(loggerName, Level.toLevel(level));

        return SUCCESS;
    }

    /**
     * 获取需要修改的日志列表
     * 
     * @return
     */
    public String loggerList() {
        initLogger2LevelMap();
        return SUCCESS;
    }

    /**
     * 获取所有日志级别
     * 
     * @return
     */
    public String[] getAllLevels() {
        List<String> levelList = new ArrayList<String>();
        levelList.add(Level.OFF.toString());
        levelList.add(Level.TRACE.toString());
        levelList.add(Level.ERROR.toString());
        levelList.add(Level.WARN.toString());
        levelList.add(Level.INFO.toString());
        levelList.add(Level.DEBUG.toString());
        return levelList.toArray(new String[0]);
    }

    private void initLogger2LevelMap() {
        logger2LevelMap = new TreeMap<String, String>(new Comparator<Object>() {

            @Override
            public int compare(Object arg0, Object arg1) {
                String loggerName0 = (String) arg0;
                String loggerName1 = (String) arg1;
                return loggerName0.compareTo(loggerName1);
            }

        });

        loggerNameKeyword = StringUtils.defaultString(loggerNameKeyword);

        List<Logger> loggers = LogbackUtils.getAllLoggers();

        for (Logger logger : loggers) {
            if (logger.getName().startsWith("net.zdsoft") && logger.getName().indexOf(loggerNameKeyword) != -1) {
                logger2LevelMap.put(logger.getName(), logger.getEffectiveLevel().toString());
            }
        }

    }

    public void setLogName(String logName) {
        this.logName = logName;
    }

    public List<File> getLogs() {
        return logs;
    }

    public void setLoggerName(String loggerName) {
        this.loggerName = loggerName;
    }

    public void setLevel(String level) {
        this.level = level;
    }

    public String getLoggerNameKeyword() {
        return loggerNameKeyword;
    }

    public void setLoggerNameKeyword(String loggerNameKeyword) {
        this.loggerNameKeyword = loggerNameKeyword;
    }

    public Map<String, String> getLogger2LevelMap() {
        return logger2LevelMap;
    }

    public String getLoggerName() {
        return loggerName;
    }

    public List<FileDto> getLogDtos() {
        return logDtos;
    }

}
